package com.unlcn.ils.wms.backend.service.inspectApp.impl;

import cn.huiyunche.commons.constant.QiniuConstant;
import cn.huiyunche.commons.exception.BusinessException;
import cn.huiyunche.commons.utils.QiniuUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpAttachBO;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpBO;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpConstantBO;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpDetailBO;
import com.unlcn.ils.wms.backend.enums.DeleteFlagEnum;
import com.unlcn.ils.wms.backend.enums.TmsInsepectExcpStatusEnum;
import com.unlcn.ils.wms.backend.enums.TmsInspectStatusEnum;
import com.unlcn.ils.wms.backend.enums.WmsExcpStatusEnum;
import com.unlcn.ils.wms.backend.enums.excp.ExcpStatusEnum;
import com.unlcn.ils.wms.backend.service.inspectApp.TmsInspectExcpService;
import com.unlcn.ils.wms.base.dto.TmsInspectExcpDTO;
import com.unlcn.ils.wms.base.dto.WmsInspectForAppDTO;
import com.unlcn.ils.wms.base.mapper.inbound.WmsInboundOrderMapper;
import com.unlcn.ils.wms.base.mapper.inspectApp.*;
import com.unlcn.ils.wms.base.model.inbound.WmsInboundOrder;
import com.unlcn.ils.wms.base.model.inbound.WmsInboundOrderExample;
import com.unlcn.ils.wms.base.model.inspectApp.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 入库异常业务
 */
@Service
public class TmsInspectExcpServiceImpl implements TmsInspectExcpService {

    private Logger logger = LoggerFactory.getLogger(TmsInspectExcpServiceImpl.class);

    private static final Boolean DELETED_BL = false;

    @Autowired
    private TmsInspectExcpConstantMapper tmsInspectExcpConstantMapper;
    @Autowired
    private TmsInspectLogMapper tmsInspectLogMapper;
    @Autowired
    private TmsInspectExcpMapper tmsInspectExcpMapper;
    @Autowired
    private TmsInspectComponentMissMapper tmsInspectComponentMissMapper;
    @Autowired
    private TmsInspectExcpExpandMapper tmsInspectExcpExpandMapper;
    @Autowired
    private TmsInspectExcpAttachsMapper tmsInspectExcpAttachsMapper;
    @Autowired
    private WmsInboundOrderMapper wmsInboundOrderMapper;


    @Value("${tms.pickup.host.url}")
    private String propertyUrl;

    @Value("${tms.pickup.host.timeout}")
    private String propertyTime;

    @Value("${tms.encode.key}")
    private String propertyKey;


    /**
     * <p>
     * 2018-5-9 异常质损分类表中增加仓库code区分
     * </p>
     *
     * @param dto 参数封装
     */
    @Override
    public List<TmsInspectExcpConstantBO> getInspectExcpList(WmsInspectForAppDTO dto) {
        logger.info("TmsInspectExcpServiceImpl.getInspectExcpList param dto:{}.", dto);
        if (Objects.equals(dto, null)) {
            throw new BusinessException("参数不能为空");
        }
        Integer positionId = dto.getPositionId();
        String whCode = dto.getWhCode();
        if (positionId == null) {
            throw new BusinessException("positionId 不能为空!");
        }
        if (StringUtils.isBlank(whCode)) {
            throw new BusinessException("仓库code不能为空!");
        }
        List<TmsInspectExcpConstantBO> constantList_Level2 = new ArrayList<>();
        TmsInspectExcpConstantExample example = new TmsInspectExcpConstantExample();
        //异常质损分类表中增加仓库code区分
        example.createCriteria()
                .andCodeEqualTo(positionId)
                .andWhCodeEqualTo(whCode)
                .andEnableEqualTo(true);
        List<TmsInspectExcpConstant> list = tmsInspectExcpConstantMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return constantList_Level2;
        }
        example = new TmsInspectExcpConstantExample();
        example.createCriteria()
                .andParentCodeEqualTo(positionId)
                .andEnableEqualTo(true)
                .andWhCodeEqualTo(whCode);
        List<TmsInspectExcpConstant> childLv2 = tmsInspectExcpConstantMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(childLv2)) {
            return constantList_Level2;
        }
        for (TmsInspectExcpConstant entity : childLv2) {
            TmsInspectExcpConstantBO bo = new TmsInspectExcpConstantBO();
            BeanUtils.copyProperties(entity, bo);
            example = new TmsInspectExcpConstantExample();
            example.createCriteria().andParentCodeEqualTo(entity.getCode())
                    .andWhCodeEqualTo(whCode)
                    .andEnableEqualTo(true);
            List<TmsInspectExcpConstant> childLv3 = tmsInspectExcpConstantMapper.selectByExample(example);
            List<TmsInspectExcpConstantBO> constantList_level3 = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(childLv3)) {
                for (TmsInspectExcpConstant entity2 : childLv3) {
                    TmsInspectExcpConstantBO bo_level3 = new TmsInspectExcpConstantBO();
                    BeanUtils.copyProperties(entity2, bo_level3);
                    constantList_level3.add(bo_level3);
                }
            }
            bo.setChildExcp(constantList_level3);
            constantList_Level2.add(bo);
        }
        return constantList_Level2;
    }

    /**
     * <>p
     * 2018-5-8  新需求调整：异常常量增加仓库code区分
     * </p>
     *
     * @param inspectId 验车id
     * @param whCode    仓库code
     * @return 返回值
     */

    @Override
    public List<TmsInspectExcpDTO> getPositionExcpCountByInspectId(Long inspectId, String whCode) {
        logger.info("TmsInspectExcpServiceImpl.getPositionExcpCountByInspectId param Long:{}", inspectId);
        if (Objects.equals(inspectId, null)) {
            logger.info("TmsInspectExcpServiceImpl.getPositionExcpCountByInspectId param Long must not be null");
            throw new BusinessException("运单id不能为空!");
        }
        List<TmsInspectExcpDTO> result_list = new ArrayList<>();
        //获取九大区域
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
        params.put("parentCode", 0);
        params.put("whCode", whCode);
        List<TmsInspectExcpDTO> positionList = tmsInspectExcpExpandMapper.selectPositionsByInspectId(params);
        if (CollectionUtils.isEmpty(positionList)) {
            throw new BusinessException("获取九大区域异常");
        }
        for (TmsInspectExcpDTO position : positionList) {
            //统计异常的数量
            TmsInspectExcpDTO result = new TmsInspectExcpDTO();
            params.put("inspectId", inspectId);
            params.put("closedCode", ExcpStatusEnum.CLOSED.getCode());
            params.put("positionId", position.getPositionId());
            int count = tmsInspectExcpExpandMapper.selectExcpCountByPositionIdAndInspectId(params);
            result.setPositionId(position.getPositionId());
            result.setConstantPositionName(position.getConstantPositionName());
            result.setConstantPositionSort(position.getConstantPositionSort());
            result.setCountExcp(count);
            result_list.add(result);
        }
        return result_list;
    }


    @Override
    public List<TmsInspectExcp> getTmsInspectExcpByBillId(Long id) {
        logger.info("TmsInspectExcpServiceImpl.getTmsInspectExcpByBillId param Long:{}", id);
        TmsInspectExcpExample excpExample = new TmsInspectExcpExample();
        TmsInspectExcpExample.Criteria criteria = excpExample.createCriteria();
        criteria.andDelFlagNotEqualTo(DELETED_BL);
        criteria.andInspectIdEqualTo(id);
        return tmsInspectExcpMapper.selectByExample(excpExample);
    }


    @Override
    public void saveNoteExcp(TmsInspectExcpBO bo) {
        if (Objects.equals(bo, null)) {
            throw new BusinessException("传入参数不能为空");
        }
        String whCode = bo.getWhCode();
        Long inspectId = bo.getInspectId();
        Integer positionId = bo.getPositionId();
        String excpDetails = bo.getExcpDetails();
        if (Objects.equals(inspectId, null)) {
            throw new BusinessException("验车单Id不能为空");
        }
        if (Objects.equals(positionId, null)) {
            throw new BusinessException("区域Id不能为空");
        }
        if (Objects.equals(bo.getUserId(), null)) {
            throw new BusinessException("用户id不能为空!");
        }
        if (StringUtils.isBlank(whCode)) {
            throw new BusinessException("仓库code不能为空!");
        }
        //判断该验车是否是合格状态,合格状态不能再标记异常
        WmsInboundOrder bill = wmsInboundOrderMapper.selectByPrimaryKey(inspectId);
        if (!Objects.equals(bill, null)) {
            if (Objects.equals(bill.getInspectStatus(), TmsInspectStatusEnum.WAYBILL_QUALIFY.getValue())) {
                throw new BusinessException("合格车辆不能进行异常标记");
            }
            if (Objects.equals(bill.getInspectStatus(), TmsInspectStatusEnum.WAYBILL_CONFIRM_EXCP.getValue())) {
                throw new BusinessException("该车辆已经验车登记不能再标记异常!");
            }
            //2添加对应positionid的异常
            //Gson gson = new Gson();
            //List<TmsInspectExcpDetailBO> detailList = gson.fromJson(excpDetails,
            //        new TypeToken<List<TmsInspectExcpDetailBO>>() {
            //        }.getType());
            List<TmsInspectExcpDetailBO> detailList = JSONObject.parseArray(excpDetails, TmsInspectExcpDetailBO.class);
            //删除老的异常信息
            deleteOldExcpListAndAttaches(bo);
            //如果异常信息为空
            if (CollectionUtils.isEmpty(detailList)) {
                int excpValue = TmsInsepectExcpStatusEnum.BILL_UNTREATED.getValue();
                int del_flag = DeleteFlagEnum.DELETED.getValue();
                int count1 = tmsInspectExcpExpandMapper.selectExcpCountByInspectId(inspectId, excpValue, del_flag);
                //统计缺件异常数量
                TmsInspectComponentMissExample missExample = new TmsInspectComponentMissExample();
                TmsInspectComponentMissExample.Criteria criteria = missExample.createCriteria();
                criteria.andInspectIdEqualTo(bill.getOdId())
                        .andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
                int count2 = tmsInspectComponentMissMapper.countByExample(missExample);
                int count = count1 + count2;
                if (Objects.equals(count, 0)) {
                    //说明都为异常关闭状态,修改验车单为待验车状态
                    modifyInspectStatus(bill, bo.getUserId(), TmsInspectStatusEnum.WAYBILL_INIT.getValue());
                }
            } else {
                //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");//设置维修分组的时间戳
                for (TmsInspectExcpDetailBO excpBO : detailList) {
                    //先删除原来的异常和图片--因维修要展示经维修并且已关闭的异常为减少判断-在进行异常标注的时候
                    // 1.先将本次要标记的异常在之前的异常记录比对，如果在以前是存在的--就将时间戳及异常类型设置为空(标记异常的时候)
                    //2.插入本次标记的异常及关联的图片
                    //3.再将原来不存在于本次标记异常类的数据并且含有时间戳的数据统一更新为当前要标注的一批的时间戳(验车登记的时候)
                    TmsInspectExcpExample excpExample = new TmsInspectExcpExample();
                    excpExample.createCriteria().andInspectIdEqualTo(inspectId)
                            .andConstantBodyCodeEqualTo(excpBO.getConstantBodyCode())
                            .andConstantHurtCodeEqualTo(excpBO.getConstantHurtCode())
                            .andExcpTimestampIsNotNull();
                    TmsInspectExcp inspectExcp = new TmsInspectExcp();
                    inspectExcp.setExcpTypeCode(null);
                    inspectExcp.setExcpTimestamp(null);
                    inspectExcp.setGmtUpdate(new Date());
                    tmsInspectExcpMapper.updateByExampleSelective(inspectExcp, excpExample);
                    //将异常和验车单关联
                    //判断本次有没有包含上一次的异常--维修合格或者不合格的异常
                    excpBO.setPositionId(positionId);
                    TmsInspectExcp excp = new TmsInspectExcp();
                    excp.setInspectId(inspectId);
                    excp.setPositionId(positionId);
                    excp.setConstantBodyCode(excpBO.getConstantBodyCode());
                    excp.setConstantHurtCode(excpBO.getConstantHurtCode());
                    excp.setDealStatus(WmsExcpStatusEnum.UNTREATED.getValue());//未处理
                    excp.setDelFlag(true);
                    excp.setWhCode(whCode);
                    excp.setGmtCreate(new Date());
                    excp.setGmtUpdate(new Date());
                    tmsInspectExcpMapper.insertSelective(excp);
                    //excpIdList.add(excp.getId());
                    // 保存附件
                    String[] attachs = excpBO.getAttachs().split(",");
                    if (!Objects.equals(attachs, null)) {
                        Arrays.stream(attachs).forEach(v -> {
                            TmsInspectExcpAttachs attach = new TmsInspectExcpAttachs();
                            attach.setPicKey(v);
                            attach.setExcpId(excp.getId());
                            attach.setGmtCreate(new Date());
                            attach.setGmtUpdate(new Date());
                            tmsInspectExcpAttachsMapper.insertSelective(attach);
                        });
                    }
                }
                modifyInspectStatus(bill, bo.getUserId(), TmsInspectStatusEnum.WAYBILL_EXCP.getValue());
            }
        }
        new Thread(() -> {
            //写入日志
            TmsInspectLog log = new TmsInspectLog();
            saveLog(bo, log);
            tmsInspectLogMapper.insertSelective(log);
        }).start();
    }


    /**
     * 入库获取区域下异常信息
     */
    @Override
    public List<TmsInspectExcpDetailBO> getInspectExcpListByPositionId(TmsInspectExcpBO bo) {
        logger.info("TmsInspectExcpServiceImpl.getInspectExcpListByPositionId param:{}", bo);
        if (Objects.equals(bo.getInspectId(), null)) {
            throw new BusinessException("验车单id不能为空!");
        }
        if (Objects.equals(bo.getPositionId(), null)) {
            throw new BusinessException("异常位置id不能为空!");
        }
        if (StringUtils.isBlank(bo.getWhCode())) {
            throw new BusinessException("仓库code 不能为空!");
        }
        //获取对应区域异常列表
        List<TmsInspectExcpDetailBO> result_list = new ArrayList<>();
        //过滤已经已经处理关闭的异常
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("inspectId", bo.getInspectId());
        params.put("positionId", bo.getPositionId());
        params.put("closeValue", WmsExcpStatusEnum.CLOSED_EXCP.getValue());
        params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
        List<TmsInspectExcpDTO> excpDTOList = tmsInspectExcpExpandMapper.selectExcpListByPositionId(params);
        if (CollectionUtils.isNotEmpty(excpDTOList)) {
            for (TmsInspectExcpDTO dto : excpDTOList) {
                //转换对象
                TmsInspectExcpDetailBO detailBO = new TmsInspectExcpDetailBO();
                BeanUtils.copyProperties(dto, detailBO);
                //获取图片的地址
                TmsInspectExcpAttachsExample attachsExample = new TmsInspectExcpAttachsExample();
                TmsInspectExcpAttachsExample.Criteria criteria = attachsExample.createCriteria();
                criteria.andExcpIdEqualTo(dto.getExcpId());
                criteria.andDelFlagEqualTo(true);
                List<TmsInspectExcpAttachs> attachsList = tmsInspectExcpAttachsMapper.selectByExample(attachsExample);
                if (CollectionUtils.isNotEmpty(attachsList)) {
                    List<TmsInspectExcpAttachBO> attachBOList = new ArrayList<>();
                    for (TmsInspectExcpAttachs attachs : attachsList) {
                        TmsInspectExcpAttachBO attachBO = new TmsInspectExcpAttachBO();
                        attachBO.setPicUrl(QiniuUtil.generateDownloadURL(QiniuConstant.QINIU_DOWNLOAD_ADDRESS, attachs.getPicKey(), "", null, null));
                        attachBO.setId(attachs.getId());
                        attachBO.setPicKey(attachs.getPicKey());
                        attachBOList.add(attachBO);
                    }
                    detailBO.setAttachBOS(attachBOList);
                }
                result_list.add(detailBO);
            }
        }
        return result_list;
    }

    /**
     * <p>
     * 2018-5-11 新增接口:一键删除所有异常 验车登记前可以删除 验车登记后需要走维修流程
     * </p>
     *
     * @param dto 参数封装
     */
    @Override
    public void deleteAllException(WmsInspectForAppDTO dto) {
        if (logger.isInfoEnabled()) {
            logger.info("TmsInspectServiceImpl.deleteAllException param:{}", dto);
        }
        if (dto == null) {
            throw new BusinessException("参数不能为空!");
        }
        Long inspectId = dto.getInspectId();
        String whCode = dto.getWhCode();
        String userId = dto.getUserId();
        if (inspectId == null) {
            throw new BusinessException("单据id不能为空!");
        }
        if (StringUtils.isBlank(whCode)) {
            throw new BusinessException("仓库code不能为空!");
        }
        if (StringUtils.isBlank(userId)){
            throw new BusinessException("用户Id不能为空!");
        }
        //查询订单信息
        WmsInboundOrderExample example = new WmsInboundOrderExample();
        example.createCriteria().andOdIdEqualTo(inspectId)
                .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
        List<WmsInboundOrder> wmsInboundOrders = wmsInboundOrderMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(wmsInboundOrders)) {
            throw new BusinessException("未查询到对应的入库信息");
        }
        WmsInboundOrder order = wmsInboundOrders.get(0);
        int excpValue = TmsInspectStatusEnum.WAYBILL_EXCP.getValue();
        if (!(excpValue == order.getInspectStatus())) {
            throw new BusinessException("只能支持异常状态进行该操作!");
        }
        //删除异常信息--
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("inspectId", inspectId);
        params.put("del", DeleteFlagEnum.DELETED.getValue());
        params.put("whCode", whCode);
        params.put("initValue", TmsInspectStatusEnum.WAYBILL_INIT.getValue());
        params.put("userId",userId);
        //params.put()
        //一键删除异常信息 将入库单验车状态改为(待验车)
        tmsInspectExcpExpandMapper.updateExceptionToDeleteByInspectId(params);
    }


    /**
     * 修改验车单状态
     */
    private void modifyInspectStatus(WmsInboundOrder inboundOrder, String userId, int value) {
        logger.info("TmsInspectExcpServiceImpl.modifyInspectStatus param :{},{},{}", inboundOrder, userId, value);
        try {
            inboundOrder.setInspectStatus(value);
            inboundOrder.setGmtUpdate(new Date());
            inboundOrder.setInspectUserId(userId);
            inboundOrder.setInspectTime(new Date());
            wmsInboundOrderMapper.updateByPrimaryKeySelective(inboundOrder);
        } catch (Exception e) {
            logger.error("TmsInspectExcpServiceImpl.modifyInspectStatus param :{},{},{}", inboundOrder, userId, value);
            throw new BusinessException("修改验车单状态异常!");
        }
    }

    private void saveLog(TmsInspectExcpBO bo, TmsInspectLog log) {
        log.setMsg("标记异常成功!");
        log.setUserId(bo.getUserId());
        log.setInspectId(bo.getInspectId());
        log.setGmtCreate(new Date());
        log.setGmtUpdate(new Date());
    }


    /**
     * 删除原来的已有数据
     */
    private void deleteOldExcpListAndAttaches(TmsInspectExcpBO bo) {
        //1先根据positionId查询删除原来数据库的数据
        TmsInspectExcpExample tmsInspectExcpExample = new TmsInspectExcpExample();
        TmsInspectExcpExample.Criteria criteria = tmsInspectExcpExample.createCriteria();
        criteria.andInspectIdEqualTo(bo.getInspectId());
        criteria.andPositionIdEqualTo(bo.getPositionId());
        criteria.andDelFlagNotEqualTo(DELETED_BL);
        List<TmsInspectExcp> exist_list = tmsInspectExcpMapper.selectByExample(tmsInspectExcpExample);
        if (CollectionUtils.isNotEmpty(exist_list)) {
            for (TmsInspectExcp inspectExcp : exist_list) {
                inspectExcp.setDelFlag(DELETED_BL);//逻辑删除
                tmsInspectExcpMapper.updateByPrimaryKeySelective(inspectExcp);
                //逻辑删除数据库中的图片
                TmsInspectExcpAttachsExample attachsExample = new TmsInspectExcpAttachsExample();
                TmsInspectExcpAttachsExample.Criteria attachsExampleCriteria = attachsExample.createCriteria();
                attachsExampleCriteria.andExcpIdEqualTo(inspectExcp.getId());
                attachsExampleCriteria.andDelFlagNotEqualTo(DELETED_BL);
                List<TmsInspectExcpAttachs> attachsList = tmsInspectExcpAttachsMapper.selectByExample(attachsExample);
                if (CollectionUtils.isNotEmpty(attachsList)) {
                    for (TmsInspectExcpAttachs attachs : attachsList) {
                        attachs.setDelFlag(false);//逻辑删除
                        attachs.setGmtUpdate(new Date());
                        tmsInspectExcpAttachsMapper.updateByPrimaryKeySelective(attachs);
                    }
                }
            }
        }
    }

}
